import { addNotification, removeNotification } from '@/utils/notificationStore'
import { NOTIFICATION_WINDOW_CHANNELS } from '~shared/ipc-topic'

// High-level API
let actionIpcInited = false
const actionCallbacks = new Map<string, (n: any) => void>()
let actionSeq = 1

function ensureActionIpcBridge() {
  if (actionIpcInited) return
  actionIpcInited = true
  try {
    // 来自主进程（经由通知窗口点击）回调到发起渲染器
    _pre_.ipcOn(NOTIFICATION_WINDOW_CHANNELS.ACTION_CLICK, (payload: { clickToken: string }) => {
      const fn = actionCallbacks.get(payload?.clickToken)
      console.log('收到通知窗口点击事件:', payload, fn)
      if (fn) {
        try {
          fn({} as any)
        } finally {
          actionCallbacks.delete(payload.clickToken)
        }
      }
    })
  } catch {
    /* empty */
  }
}

function ensureNotifyReceiver() {
  try {
    // 供主进程调用：把 options 下发到本渲染器内执行 notify()
    _pre_.ipcOn(NOTIFICATION_WINDOW_CHANNELS.NOTIFY, (options: Notify.NotificationOptions) => {
      console.log('[notify] 收到主进程通知请求:', options)
      try {
        notify(options)
      } catch (error) {
        console.error('[notify] handle main notify failed', error)
      }
    })
  } catch {
    /* empty */
  }
}

function attachActionTokens(opt: Notify.NotificationOptions): Notify.NotificationOptions {
  if (!opt?.actions?.length) return opt
  const next = { ...opt }
  next.actions = opt.actions.map(a => {
    if (typeof a.onClick === 'function') {
      const token = `act_${Date.now()}_${actionSeq++}`
      actionCallbacks.set(token, a.onClick)
      return { id: a.id, label: a.label, color: a.color, clickToken: token }
    }
    return { id: a.id, label: a.label, color: a.color }
  }) as any
  return next
}

export function notify(options: Notify.NotificationOptions): Notify.NotificationItem | void {
  const normalized = resolvePosition(options)
  if (normalized.level === 'system') {
    return showSystemNotification(normalized)
  }
  // 统一从渲染进程经由 IPC 交由主进程显示独立通知窗口
  try {
    if (typeof _pre_ !== 'undefined' && _pre_.ipcInvoke) {
      ensureActionIpcBridge()
      const withTokens = attachActionTokens(normalized)
      const sanitized = sanitizeOptions({ ...withTokens, level: 'in-app' })
      _pre_.ipcInvoke(NOTIFICATION_WINDOW_CHANNELS.SHOW, sanitized)
      return
    }
  } catch (error) {
    console.warn('[notify] 通过主进程显示通知失败，回退到应用内通知:', error)
  }
  // 如 IPC 不可用，仅在开发/降级情况下回退为应用内渲染
  return addNotification({ ...normalized, level: 'in-app' })
}

export function notifyInfo(
  message: string,
  title?: string,
  opt: Partial<Notify.NotificationOptions> = {}
) {
  return notify({ ...opt, level: opt.level ?? 'in-app', variant: 'info', message, title })
}

export function notifySuccess(
  message: string,
  title?: string,
  opt: Partial<Notify.NotificationOptions> = {}
) {
  return notify({ ...opt, level: opt.level ?? 'in-app', variant: 'success', message, title })
}

export function notifyWarning(
  message: string,
  title?: string,
  opt: Partial<Notify.NotificationOptions> = {}
) {
  return notify({ ...opt, level: opt.level ?? 'in-app', variant: 'warning', message, title })
}

export function notifyError(
  message: string,
  title?: string,
  opt: Partial<Notify.NotificationOptions> = {}
) {
  return notify({ ...opt, level: opt.level ?? 'in-app', variant: 'error', message, title })
}

export function closeNotification(id: string) {
  removeNotification(id)
}

// System-level notifications using Web Notification API (Electron renderer supports this)
export function showSystemNotification(
  options: Notify.NotificationOptions
): Notify.NotificationItem | void {
  console.log('显示系统通知', options, typeof window, Notification.permission)
  if (typeof window === 'undefined' || typeof Notification === 'undefined') {
    // fallback to in-app
    return addNotification({ ...options, level: 'in-app' })
  }

  const show = () => {
    try {
      new Notification(options.title || 'Notification', {
        body: options.message,
        icon: options.icon,
        silent: false
      })
      // Optionally mirror to in-app for visibility
      if (options.position !== 'custom') {
        return addNotification({ ...options, level: 'in-app' })
      }
    } catch {
      console.log('显示系统通知失败，使用应用内通知')
      return addNotification({ ...options, level: 'in-app' })
    }
  }

  if (Notification.permission === 'granted') return show()
  if (Notification.permission !== 'denied') {
    Notification.requestPermission().then(() => show())
    return
  }
  // denied -> fallback to in-app
  return addNotification({ ...options, level: 'in-app' })
}

// -------- helpers --------
function sanitizeOptions(options: Notify.NotificationOptions): Notify.NotificationOptions {
  if (!options?.actions || options.actions.length === 0) return options
  return {
    ...options,
    actions: options.actions.map(a => ({
      id: a.id,
      label: a.label,
      color: a.color,
      clickToken: a.clickToken
    }))
  }
}

export { notificationState } from '@/utils/notificationStore'

export function resolvePosition(opt: Notify.NotificationOptions): Notify.NotificationOptions {
  const allowed: Notify.NotificationPosition[] = [
    'top-left',
    'top-center',
    'top-right',
    'bottom-left',
    'bottom-center',
    'bottom-right',
    'custom'
  ]
  const position = allowed.includes((opt.position as any) ?? '')
    ? (opt.position as Notify.NotificationPosition)
    : 'top-right'

  if (position !== 'custom') {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const { x, y, ...rest } = opt
    return { ...rest, position }
  }

  const x = typeof opt.x === 'number' && Number.isFinite(opt.x) ? Math.max(0, opt.x) : 0
  const y = typeof opt.y === 'number' && Number.isFinite(opt.y) ? Math.max(0, opt.y) : 0
  return { ...opt, position: 'custom', x, y }
}

// 初始化：默认开启来自主进程的通知接收
try {
  ensureNotifyReceiver()
} catch {
  /* empty */
}
